home *** CD-ROM | disk | FTP | other *** search
-
- /************************************************************************/
-
- /* File KDISK.C - Disk & File Handling Support for Kermit.
- Chris Kennington 5th July 1985. */
-
-
- #include "stdio.h"
-
- #ifdef MPUZ80 /* 480Z */
-
- #ifndef TINY
- #include "io.h"
- #endif
-
- #else /* Nimbus */
-
- /* Layout of FCB (as in <io.h>): */
- struct fcb {
- char f_driv;
- char f_name[8];
- char f_type[3];
- char f_ext;
- char f_resv[2];
- char f_rc;
- char f_sydx[16];
- char f_cr;
- unsigned f_record; char f_overfl;
- };
-
- /* displacements in block returned by Find Match/Next File:- */
- #define MCHATTRIB 21
- #define MCHNAME 30
-
- /* workspace for MCH* */
- static char dmabuf[65];
-
- #endif
-
- #include "ctype.h"
-
- #define DEFS2 1
- #define DEFS5 1
-
- #include "b:kext.h"
-
- #define DMA 0x0080 /* use default DMA */
-
-
- /* The routines in this file provide OS-independent support on Aztec-C
- for the disk-maintenance functions:
- CHAnge (reset all drives)
- DIR dname/dfname
- ERAse dfname (DEL is synonym)
- HELP (print help-text; ? is synonym)
- REName fname fname
- TYPe dfname
- UPAth (show environment)
- USEr num (CP/M only)
- [DRIve] dname
- (only first 3 chars need be entered)
-
- where the valid arguments are:-
- dname - a valid disk-letter;
- fname - a valid file-name (on default disk);
- dfname - a valid file-name with optional disk-letter;
- num - a valid user-number.
-
-
- Standard Return-Code Byte:
- bit 0 - file not found
- bit 1 - filename invalid
- bit 2 - disk-letter invalid
- bit 3 - system file
- bit 4 - file is read/only
- bit 5 - disk is temporarily read-only (CP/M)
- bit 6 - wildcards in name
- bit 7 - directory-name (MSDOS)
- */
-
-
-
- /* static variables for intercommunication */
- static char *s1, *s2; /* => names 1 & 2 */
- static char cmd; /* command-number */
- static char *cmds[] = { /* valid commands */
- "Nul", "DIR", "ERA", "REN", /* 0-3 (0 is unused) */
- "TYP", "USE", "UPA", "DRI", /* 4-7 */
- "DEL", "CHA", "HEL", /* 8-10 */
- 0}; /* zero to terminate */
-
- static char allfiles[] = "*.*";
- static char diskro[] = "(disk r/o) ";
- static char exists[] = " <%s> already exists, ";
- static char explicit[15]; /* new filename */
- static char inval[] = "invalid";
- static char invalid[] = " <%s> now invalid ";
- static char notdel[] = " NOT deleted.";
- static char notren[] = " NOT renamed.";
- static char overw[] = "overwritten ";
- static char reject[] = "rejecting <%s>.";
- static char wildcds[] = "has wildcards";
- /* working variables */
- static char c, cold, rtn, rtnall, *e, *w;
-
- /* Displayed text which needs to vary between CP/M & MSDOS */
- #ifdef MPUZ80
- char diskcmds[] = " CHAnge DIRectory DRIve ERAse REName TYPe USEr UPAth";
- char diskfail[] = "Disk failure, CP/M code %d";
- char os1[] = "\r The following commands are valid (only 3 letters needed):\r\
- CHAnge floppy; DRIve change; DIRectory list; ERAse file(s);";
- char os2[] = "\r\
- REName file; TYPe file; USEr-number; UPAth (show defaults).\
- \r Wildcards (? *) accepted in DIR & ERA.";
- #else
- char diskcmds[] = " DELete DIRectory DRIve REName TYPe UPAth";
- char diskfail[] = "Disk failure, MSDOS code %d";
-
- char os1[] = "\r The following commands are valid (only 3 letters needed):\r\
- DELete file(s); DRIve change; DIRectory list;";
- char os2[] = "\r\
- REName file; TYPe file; UPAth (show path).\
- \r Wildcards (? *) accepted in DIR & DEL.";
- #endif
-
-
-
-
- char *avoid(file) /* implement collison avoidance */
- /* If the requested file already exists, queries setting of
- nmavoid and acts accordingly;
- Returns 0 if file not there or may be overwritten,
- else address of explanatory string. */
- char *file; /* file-name */
- {
- static char ret;
- char c, *r2;
- int len;
-
- keyget(&c); /* trap ESC */
- ret = filechek(0,file,work);
- if ( (ret & (char)0x01) != 0 )
- return(0); /* no such file */
- if ( (ret & (char)0x06) != 0 )
- return(invalid); /* bad name */
-
- /* file exists - see what to do about it */
- outc(CR);
- printf(exists,file);
- switch(nmavoid) { /* break if OK, return if not */
-
- case 0: /* overwrite */
- txtout(overw);
- break;
-
- case 1: /* avoid by renaming */
- if ( (len = strlen(file) - 1) < 2 ) {
- len = 2;
- file[2] = '0';
- }
- if (file[len-1] == '.') {
- len += 2;
- file[len] = '0';
- }
- c = file[len];
- if (file[len-1] == '$')
- file[len] = ++c; /* increment last char */
- else
- file[len-1] = '$'; /* or set previous to $ */
- file[len+1] = 0; /* ensure closed */
- if ( (r2 = avoid(file)) == 0 )
- break; /* then check that */
- else
- return(r2);
-
- case 2: /* reject incoming file */
- return(reject);
-
- case 3: /* check with user */
- printf("OK if %s",overw);
- if (confirm())
- break; /* Yes */
- else
- return(reject);
-
- default: /* unkmown setting */
- return(null);
- } /* end switch */
- vtline(LOCFILE,file);
-
- /* Make sure BDOS will not prevent overwriting */
- if ( (ret & (char)0x30) != 0 )
- return("<%s> is read-only ");
- else
- return(0);
- } /* End of avoid() */
-
-
-
- char dirprt(name) /* list directory-matches */
- /* Leaves expanded name in "explicit" and sets up "ownfcb";
- Returns composite status-byte. */
- char *name;
- {
- char ret;
-
- cold = 0;
- ret = rtn = fileok(name);
- outfc(CR);
- if ( (rtn & (char)0x07) != 0 )
- return(rtn); /* not found or invalid */
- else do {
- ret |= rtn;
- for (c=0; c<26; ++c)
- work[c] = SP;
- work[c] = 0;
- w = work;
- e = explicit;
- while( (*w = *e++) != 0)
- ++w;
- if ( (rtn & (char)0x08) != 0 ) {
- e = " sys";
- while( (*w = *e++) != 0)
- ++w;
- }
- if ( (rtn & (char)0x10) != 0 ) {
- e = " r/o";
- while( (*w = *e++) != 0)
- ++w;
- }
- *w = ',';
- txtout(work);
- if (++cold > 2) { /* in 3 columns of 25 ch */
- if (outfc(CR) != 0) {
- txtout("\rList aborted");
- return(ret); /* abort list */
- }
- cold = 0;
- }
- } while ( ( (rtn = filechek(1,name,explicit)) & (char)0x01) == 0 ) ;
- return(ret);
- } /* End of dirprt() */
-
-
-
- char filechek(mode,fname,nuname) /* verify disk-file */
- /* Returns standard status-byte to give situation of file;
- sets up ownfcb with expanded wildcard name & checks for it;
- if file exists, copies explicit name into *nuname */
- char mode, *fname, *nuname;
- {
- char c, disk, ret, *name;
- int i, w, attrib;
- struct fcb *fcb2;
-
- bdos(SETDMA,DMA);
- name = fname;
- /* validate disk-letter if any */
- if (fname[1] == ':') { /* if disk quoted */
- disk = fname[0] & 0x5f;
- fname += 2; /* up to filename */
- if ( (disk < 'A') || (disk > 'P') )
- return(0x04); /* bad disk-letter */
- disk &= 0x3f; /* range 1-16 = A-P */
- if (*fname == 0) { /* disk-letter only */
- #ifdef MPUZ80 /* simple for CP/M */
- fname = allfiles; /* point to *.* */
- #else /* whole path needed for MSDOS */
- e = fname;
- w = allfiles;
- while ( (*e++ = *w++) != 0 )
- ; /* copy *.* into name */
- #endif
- } }
- else
- disk = 0;
- ownfcb->f_driv = disk; /* set up drive-code */
-
- /* validate name */
- if ( (w = filexpand(fname,ownfcb->f_name)) < 0 )
- return(0x02); /* bad name */
- ret = (w > 0) ? 0x40 : 0;
-
- #ifdef MPUZ80 /* CP/M handling
- mode += SCHFST; /* search first or next */
- if ( (i = bdos(mode,ownfcb)) == 0xff)
- return(0x01); /* not found */
- fcb2 = DMA + (i * 32);
- name = fcb2->f_name; /* explicit name + bits */
- for (i=0; i<11; ++i) {
- if (i == 8)
- *nuname++ = '.';
- if ( (c = (name[i] & (char)0x7f)) != SP )
- *nuname++ = c;
- }
- if ( *(nuname-1) == '.' )
- --nuname;
- *nuname = 0; /* close string */
- /* check for special conditions */
- if ( (fcb2->f_type[0] & (char)0x80) != 0 )
- ret |= 0x10; /* file r/o */
- if ( (fcb2->f_type[1] & (char)0x80) != 0 )
- ret |= (char)0x08; /* system file */
-
- #else /* MSDOS handling */
- fname = name; /* retreive original name */
- bdos(SETDMA,dmabuf);
- mode += MCHFST;
- attrib = 0xffff; /* find all files/dirs */
- if (dos(mode,0,attrib,fname,0,0) == -1)
- return(0x01);
- name = dmabuf + MCHNAME; /* name found */
- attrib = *(dmabuf + MCHATTRIB); /* & its attributes */
- while ( (*nuname = *name++) > SP )
- ++nuname;
- *nuname = 0; /* overwrites first space/ctrl */
- /* check for special conditions */
- if ( (attrib & (char)0x01) != 0 )
- ret |= (char)0x10; /* file r/o */
- if ( (attrib & (char)0x06) != 0 )
- ret |= (char)0x08; /* system file */
- if ( (attrib & (char)0x10) != 0 )
- ret |= (char)0x80; /* directory */
- if ( (attrib & (char)0x08) != 0 ) {
- w = " (Vol-Id)";
- while ( (*nuname++ = *w++) != 0 )
- ;
- }
-
- #endif
-
- if (disk == 0)
- disk = bdos(CURDSK,0); /* default disk */
- else
- --disk;
- /* disk now = 0-15 for A-P */
- if (rochek(disk) != 0 )
- ret |= (char)0x20; /* disk r/o */
- return(ret); /* normal return */
- } /* end of filechek() */
-
-
-
- char fileok(nam) /* check & print if bad */
- /* Leaves ownfcb set up for subsequent routines;
- Returns standard status-byte. */
- char *nam;
- {
- char ret;
-
- ret = filechek(0,nam,explicit);
- if ( (ret & (char)0x20) != 0 )
- txtout(diskro);
- if ( (ret & (char)0x06) != 0 )
- printf("<%s> %s ",nam,inval);
- #ifndef MPUZ80 /* only for MSDOS */
- else if ( (ret & (char)0x80) != 0 )
- printf("(dir) ");
- #endif
- else if ( (ret & (char)0x01) != 0 )
- printf("<%s> not found ",nam);
- return(ret);
- } /* end of fileok() */
-
-
-
- filexpand(fname,nuname) /* expand & check filename */
- /* returns -1 for error, 0 for OK, +1 for OK with wildcards
- fname must not have a disk-letter */
- char *fname, *nuname; /* old & new names */
- {
- char c, wild;
- int i, lim;
-
-
- for (i=0; i<11; ++i) /* blanx to nuname */
- nuname[i] = SP;
- nuname[11] = 0;
-
- wild = 0;
- lim = 8; /* first part */
- i = 0;
-
- while (i < 11) switch (c = *fname++) {
-
- case '?': /* wildcard */
- wild = 1;
- if (i < lim)
- nuname[i++] = c; /* stored */
- else
- return(-1);
- break;
-
- case '*': /* multi-wildcard */
- wild = 1;
- while (i < lim)
- nuname[i++] = '?'; /* stored */
- break;
-
- case '.': /* separator */
- if ( (i == 0) || (lim == 11) ) /* leading dot or */
- return(-1); /* second dot - invalid */
- else {
- i = 8;
- lim = 11;
- }
- break;
-
- case 0: /* end-of-string */
- if (i == 0)
- return(-1); /* null name */
- --fname;
- i = 11;
- break;
-
- default: /* all others */
- if ( ( (isalnum(c) == 0) && (c != '$') ) /* bad char */
- || (i >= lim) ) /* too many chars */
- return(-1);
- else
- nuname[i++] = c; /* stored */
- break;
- } /* end switch, while */
- if (*fname != 0) /* surplus char(s) */
- wild = -1;
- return(wild);
- } /* end of filexpand() */
-
-
-
-
- findcmd(osl) /* structure user input */
- /* Sets up cmd with cmd-no, s1 & s2 => names (zero-terminated);
- Returns number of valid items, 0 - 3; -1 if string is null;
- (If command invalid, returns 0 with s2 => invalid string). */
- char *osl;
- {
- static char *ospm[4];
- char c;
- int i;
-
- cmd = 4;
- while (cmd-- > 0) /* clear ospm[] */
- ospm[cmd] = 0; /* (leaves cmd = 0) */
- decol8(osl,ospm,4);
- if ( (s1=ospm[0]) == 0) /* null goes back to Kermit */
- return(-1);
- if (s1[1] == 0) switch (*s1) { /* 1-letter inputs */
- case 'Q':
- kermkill(0);
- case 'K':
- return(-1);
- case '?':
- cmd = 10;
- return(1);
- default:
- return(0);
- }
- if ( (s1[1] == ':') && (s1[2] == 0) ) { /* disk-letter */
- cmd = 7;
- return(1);
- }
-
- /* identify command */
- i = 0;
- while ( (s2 = cmds[++i]) != 0 ) {
- s1 = ospm[0];
- while ( ( (c = *s2) == *s1) && (c != 0) ) { /* match chars */
- ++s1;
- ++s2;
- }
- if (c == 0) { /* whole command */
- cmd = (char)i;
- break;
- } }
- if (cmd == 0) {
- s1 = 0;
- s2 = ospm[0];
- return(0); /* no match */
- }
-
- /* set up statics & return with count */
- s1 = ospm[1];
- if (*(s2 = ospm[2]) == '=')
- s2 = ospm[3];
- return(c);
-
- } /* end of findcmd() */
-
-
-
- char osaction() /* take action on disk/os command */
- /* Get cmdline from user and take action on it; on null input
- return 0, else 1. */
- {
- static FILE *tfp;
- int ic, disk, user;
- char d;
-
- txtout(oprompt);
- keyline(osline);
- upper(osline);
- scrline = 0; /* clear paging */
- if (findcmd(osline) < 0) /* set up cmd, s1, s2 */
- return(0); /* exit on null line */
-
- if (s1 == 0)
- s1 = allfiles;
- if (s2 == 0)
- s2 = allfiles;
-
- switch (cmd) {
-
- case 0: /* Null command */
- printmsg(" <%s> - Not a valid command.",s2);
- break;
-
- case 1: /* DIR */
- printf(" %s Directory for %s - ", userpath(),s1);
- dirprt(s1);
- break;
-
- case 2: /* ERA */
- case 8: /* DEL */
- printmsg(" DELete command: ");
- if ( (dirprt(s1) & (char)0x30) != 0 ) {
- outc(CR);
- printf(" R/O -%s",notdel);
- break;
- }
- /* seek confirmation before deleting */
- txtout("\r OK to delete");
- if (confirm() == 0) {
- printf(" Files%s",notdel);
- break;
- }
- outc(CR);
- printf(" Deleting %s: ",s1);
- if (bdos(DELFIL,ownfcb) == (char)0x0ff )
- printf("failed;%s",notdel);
- else
- txtout("Files deleted.");
- break;
-
- case 3: /* REN */
- #ifndef MPUZ80
- /* CP/M renames A <= B but MSDOS renames A => B, so switch names for MSDOS */
- w = s1;
- s1 = s2;
- s2 = w;
- #endif
- printf(" RENaming %s to %s; ",s2,s1);
- if ( (s1[1] == ':') || (s2[1] == ':') ) {
- printf("Omit driveletter;%s",notren);
- break;
- }
- /* check new (first) name */
- if ( (rtn = filexpand(s1,work)) != 0 ) {
- printf("%s %s; %s", s1, (rtn!=1) ? inval : wildcds, notren);
- break;
- }
- rtn = filechek(0,s1,explicit);
- if ( (rtn & (char)0x01) == 0 ) {
- printf("%s exists -%s",s1,notren);
- break;
- }
- /* check old (second) name */
- if ( (rtn = filexpand(s2,explicit)) != 0 ) {
- printf("%s %s; %s", s2, (rtn!=1) ? inval : wildcds, notren);
- break;
- }
- if ( ( (rtn = fileok(s2)) & (char)0x37 ) != 0) {
- if ( (rtn & (char)0x10) != 0 )
- txtout("R/O");
- txtout(notren);
- break;
- }
- if ( (rtn & (char)0x08) != 0 )
- txtout("(sys) ");
-
-
- /* move second name into fcb + 16 */
- e = &(ownfcb->f_sydx);
- *e++ = 0; /* dummy disk */
- w = work;
- user = 12;
- while (user-- != 0)
- *e++ = *w++; /* new name */
- if (bdos(RENFIL,ownfcb) == (char)0xff)
- txtout(" Rename FAILED.");
- else
- txtout(" Renamed OK.");
- break;
-
- case 4: /* TYPE */
- txtout(" ");
- if ( (fileok(s1) & (char)0x07) != 0)
- break;
- printf("TYPing file <%s>:\r\r", explicit);
- if ( (tfp = fopen(s1,"r")) == 0 )
- txtout(" File inaccessible.");
- else while ( (ic = getc(tfp)) != EOF ) {
- c = ic;
- if (c == CTLZ)
- break; /* CP/M EOF */
- if (outfc(ascch(c)) != 0)
- break;
- }
- outfc(CR);
- if (c == CTLZ)
- printf("End of File <%s>.\r",s1);
- fclose(tfp);
- break;
-
- #ifdef MPUZ80
- case 5: /* USER (CP/M only) */
- if ( (user = atoi(s1)) > 15 )
- txtout(" User > 15 not valid");
- else {
- bdos(GETUSR,user);
- printmsg(" Now: %s", userpath());
- }
- break;
- #endif
-
- case 6: /* UPATH */
- printf(" Environment: %s ",userpath());
- break;
-
- case 7: /* DRIVE */
- txtout(" DRIVE change: ");
- disk = (*s1 & 0x5f) - 'A';
- if ( (disk < 0) || (disk > 15) )
- txtout("Only A-P are valid disks ");
- else {
- bdos(SELDSK,disk);
- txtout(userpath());
- if (rochek(disk) != 0)
- txtout(diskro);
- }
- break;
-
- #ifdef MPUZ80
- case 9: /* CHAnge disks (CP/M only) */
- bdos(SELDSK,0);
- /* if not on drive A, r/o not permanently removed */
- printmsg(" Back on %s; Change any disk & hit RETURN ",userpath());
- while (kbdin() == 0)
- ;
- bdos(RSTDRV,0xffff);
- break;
- #endif
-
- case 10: /* HELP or ? */
- txtout(os1);
- txtout(os2);
- break;
-
- default:
- txtout("???");
- break;
- } /* end switch */
- return(1); /* normal return */
- } /* end of osaction() */
-
-
-
-
- rochek(d) /* check for disk r/o */
- /* returns NZ if disk d is r/o */
- int d; /* disknumber 0-15 */
- {
- if (d > 15)
- return(-1);
- else
- #ifdef MPUZ80
- return( bdoshl(GETROV,0) & (0x0001 << d) );
- #else /* no-op under MSDOS */
- return(0);
- #endif
- } /* end of rochek() */
-
-
-
- char *userpath() /* return environment */
- /* returns address of a string of about 20 chars containing
- user-number & disk etc. */
- {
- int i;
- char disk, user;
-
- disk = bdos(CURDSK,0) + 'A';
- #ifdef MPUZ80
- /* CP/M - return disk & user-no */
- user = bdos(GETUSR,0xff);
- sprintf(work,"User %d, drive %c: ", user, disk);
- #else
- /* MSDOS - reutrn disk only (pathname doesnt work) */
- sprintf(work,"Drive %c: ", disk);
- #endif
- return(work);
- } /* end of userpath() */
-
-
-
- CHAR wildex(wild,line) /* expand wildcard names */
- /* Permits use of same workspace for two parameters, but
- "line" must be at least 85 chars long.
- Returns count of files expanded, with 80-bit set if still
- more on disk. */
- char *wild, *line;
- {
- char count = 0, dsk = 0, ic = 0;
- char local[14], *last, *next;
-
- if (wild[1] == ':') /* disk letter */
- dsk = *wild;
- next = local;
- while ( (*next++ = *wild++) != 0 )
- ;
- last = next = line;
- if (dsk != 0) { /* disk-letter to first */
- *(++next) = dsk;
- *(++next) = ':';
- }
- if ( (filechek(0,local,++next) & (char)0x01) == 0 ) do {
- if ( (++count > 8) || (ic > 70) )
- return(count + (char)0x7f); /* count & 0x80 */
- *last = SP; /* terminator => separator */
- while ( *(++next) != 0 )
- ++ic;
- last = next++;
- if (dsk != 0) { /* copy disk-letter to next */
- *next++ = dsk;
- *next++ = ':';
- }
- } while ( (filechek(1,local,next) & (char)0x01) == 0 ) ;
- /* this copies next explixcit name onto line */
- else
- *line = 0; /* null line */
- return(count);
- } /* end of wildex() */
-
- /***************** End of file KDISK.C ************************/
-
-